1 using System;
2 using
UnityEngine;
3 using
UnityStandardAssets.CrossPlatformInput;
4
5 namespace
UnityStandardAssets.Characters.FirstPerson
6 {
7     
[RequireComponent(typeof (Rigidbody))]
8     
[RequireComponent(typeof (CapsuleCollider))]
9     
public class RigidbodyFirstPersonController : MonoBehaviour
10     {
11         
[Serializable]
12         
public class MovementSettings
13         {
14             
public float ForwardSpeed = 8.0f; // Speed when walking forward
15             
public float BackwardSpeed = 4.0f; // Speed when walking backwards
16             
public float StrafeSpeed = 4.0f; // Speed when walking sideways
17             
public float RunMultiplier = 2.0f; // Speed when sprinting
18             
public KeyCode RunKey = KeyCode.LeftShift;
19             
public float JumpForce = 30f;
20             
public AnimationCurve SlopeCurveModifier = new AnimationCurve(new Keyframe(-90.0f, 1.0f), new Keyframe(0.0f, 1.0f), new Keyframe(90.0f, 0.0f));
21             [HideInInspector]
public float CurrentTargetSpeed = 8f;
22            
23 #
if !MOBILE_INPUT
24             
private bool m_Running;
25 #endif
26
27             
public void UpdateDesiredTargetSpeed(Vector2 input)
28             {
29                 
if (input == Vector2.zero) return;
30                 
if (input.x > 0 || input.x < 0)
31                 {
32                     
//strafe
33                     CurrentTargetSpeed = StrafeSpeed;
34                 }
35                 
if (input.y < 0)
36                 {
37                     
//backwards
38                     CurrentTargetSpeed = BackwardSpeed;
39                 }
40                 
if (input.y > 0)
41                 {
42                     
//forwards
43                     
//handled last as if strafing and moving forward at the same time forwards speed should take precedence
44                     CurrentTargetSpeed = ForwardSpeed;
45                 }
46 #
if !MOBILE_INPUT
47                 
if (Input.GetKey(RunKey))
48                 {
49                     CurrentTargetSpeed *= RunMultiplier;
50                     m_Running =
true;
51                 }
52                 
else
53                 {
54                     m_Running =
false;
55                 }
56 #endif
57             }
58
59 #
if !MOBILE_INPUT
60             
public bool Running
61             {
62                 
get { return m_Running; }
63             }
64 #endif
65         }
66
67
68         
[Serializable]
69         
public class AdvancedSettings
70         {
71             
public float groundCheckDistance = 0.01f; // distance for checking if the controller is grounded ( 0.01f seems to work best for this )
72             
public float stickToGroundHelperDistance = 0.5f; // stops the character
73             
public float slowDownRate = 20f; // rate at which the controller comes to a stop when there is no input
74             
public bool airControl; // can the user control the direction that is being moved in the air
75             
[Tooltip("set it to 0.1 or more if you get stuck in wall")]
76             
public float shellOffset; //reduce the radius by that ratio to avoid getting stuck in wall (a value of 0.1f is nice)
77         }
78
79
80         
public Camera cam;
81         
public MovementSettings movementSettings = new MovementSettings();
82         
public MouseLook mouseLook = new MouseLook();
83         
public AdvancedSettings advancedSettings = new AdvancedSettings();
84
85
86         
private Rigidbody m_RigidBody;
87         
private CapsuleCollider m_Capsule;
88         
private float m_YRotation;
89         
private Vector3 m_GroundContactNormal;
90         
private bool m_Jump, m_PreviouslyGrounded, m_Jumping, m_IsGrounded;
91
92         
public float prev_y;
93         
public float curr_y;
94         
private float prev_x, prev_z;
95         
private float curr_x, curr_z;
96
97         [HideInInspector]
public float start_x;
98         [HideInInspector]
public float start_y;
99         [HideInInspector]
public float start_z;
100
101         
public Vector3 Velocity
102         {
103             
get { return m_RigidBody.velocity; }
104         }
105
106         
public bool Grounded
107         {
108             
get { return m_IsGrounded; }
109         }
110
111         
public bool Jumping
112         {
113             
get { return m_Jumping; }
114         }
115
116         
public bool Running
117         {
118             
get
119             {
120  #
if !MOBILE_INPUT
121                 
return movementSettings.Running;
122 #
else
123                 
return false;
124 #endif
125             }
126         }
127
128
129         
private void Start()
130         {
131             m_RigidBody = GetComponent<Rigidbody>();
132             m_Capsule = GetComponent<CapsuleCollider>();
133             mouseLook.Init (transform, cam.transform);
134
135             prev_y = m_RigidBody.transform.position.y;
136             curr_y = prev_y;
137
138             
// Get initial position
139             start_x = m_RigidBody.transform.position.x;
140             start_y = m_RigidBody.transform.position.y;
141             start_z = m_RigidBody.transform.position.z;
142
143         }
144
145
146         
private void Update()
147         {
148             RotateView();
149
150             
if (CrossPlatformInputManager.GetButtonDown("Jump") && !m_Jump)
151             {
152                 m_Jump =
true;
153             }
154
155             curr_y = m_RigidBody.transform.position.y;
156             curr_x = m_RigidBody.transform.position.x;
157             curr_z = m_RigidBody.transform.position.z;
158
159             
if (curr_y > prev_y + .08)
160             {
161                 
// Trying to go uphill
162                 transform.position =
new Vector3(prev_x, prev_y, prev_z);
163
164             }
else
165             {
166                 prev_y = curr_y;
167                 prev_x = curr_x;
168                 prev_z = curr_z;
169             }
170
171
172         }
173
174
175         
private void FixedUpdate()
176         {
177             GroundCheck();
178             Vector2 input = GetInput();
179
180             
if ((Mathf.Abs(input.x) > float.Epsilon || Mathf.Abs(input.y) > float.Epsilon) && (advancedSettings.airControl || m_IsGrounded))
181             {
182                 
// always move along the camera forward as it is the direction that it being aimed at
183                 Vector3 desiredMove = cam.transform.forward*input.y + cam.transform.right*input.x;
184                 desiredMove = Vector3.ProjectOnPlane(desiredMove, m_GroundContactNormal).normalized;
185
186                 desiredMove.x = desiredMove.x*movementSettings.CurrentTargetSpeed;
187                 desiredMove.z = desiredMove.z*movementSettings.CurrentTargetSpeed;
188                 desiredMove.y = desiredMove.y*movementSettings.CurrentTargetSpeed;
189                 
if (m_RigidBody.velocity.sqrMagnitude <
190                     (movementSettings.CurrentTargetSpeed*movementSettings.CurrentTargetSpeed))
191                 {
192                     m_RigidBody.AddForce(desiredMove*SlopeMultiplier(), ForceMode.Impulse);
193                 }
194             }
195
196             
if (m_IsGrounded)
197             {
198                 m_RigidBody.drag =
5f;
199
200                 
if (m_Jump)
201                 {
202                     m_RigidBody.drag =
0f;
203                     m_RigidBody.velocity =
new Vector3(m_RigidBody.velocity.x, 0f, m_RigidBody.velocity.z);
204                     m_RigidBody.AddForce(
new Vector3(0f, movementSettings.JumpForce, 0f), ForceMode.Impulse);
205                     m_Jumping =
true;
206                 }
207
208                 
if (!m_Jumping && Mathf.Abs(input.x) < float.Epsilon && Mathf.Abs(input.y) < float.Epsilon && m_RigidBody.velocity.magnitude < 1f)
209                 {
210                     m_RigidBody.Sleep();
211                 }
212             }
213             
else
214             {
215                 m_RigidBody.drag =
0f;
216                 
if (m_PreviouslyGrounded && !m_Jumping)
217                 {
218                     StickToGroundHelper();
219                 }
220             }
221             m_Jump =
false;
222         }
223
224
225         
private float SlopeMultiplier()
226         {
227             
float angle = Vector3.Angle(m_GroundContactNormal, Vector3.up);
228             
return movementSettings.SlopeCurveModifier.Evaluate(angle);
229         }
230
231
232         
private void StickToGroundHelper()
233         {
234             RaycastHit hitInfo;
235             
if (Physics.SphereCast(transform.position, m_Capsule.radius * (1.0f - advancedSettings.shellOffset), Vector3.down, out hitInfo,
236                                    ((m_Capsule.height/
2f) - m_Capsule.radius) +
237                                    advancedSettings.stickToGroundHelperDistance, Physics.AllLayers, QueryTriggerInteraction.Ignore))
238             {
239                 
if (Mathf.Abs(Vector3.Angle(hitInfo.normal, Vector3.up)) < 85f)
240                 {
241                     m_RigidBody.velocity = Vector3.ProjectOnPlane(m_RigidBody.velocity, hitInfo.normal);
242                 }
243             }
244         }
245
246
247         
private Vector2 GetInput()
248         {
249             
250             Vector2 input =
new Vector2
251                 {
252                     x = CrossPlatformInputManager.GetAxis(
"Horizontal"),
253                     y = CrossPlatformInputManager.GetAxis(
"Vertical")
254                 };
255             
//Debug.Log("y= " + input.y);
256
257             
// ALWAYS MOVE FORWARD
258             input.y = (
float).3;
259
260             movementSettings.UpdateDesiredTargetSpeed(input);
261             
return input;
262         }
263
264
265         
private void RotateView()
266         {
267             
//avoids the mouse looking if the game is effectively paused
268             
if (Mathf.Abs(Time.timeScale) < float.Epsilon) return;
269
270             
// get the rotation before it's changed
271            
// float oldYRotation = transform.eulerAngles.y;
272
273             mouseLook.LookRotation (transform, cam.transform);
274
275             
/*
276              
277             
if (m_IsGrounded || advancedSettings.airControl)
278             {
279                 // Rotate the rigidbody velocity to match the
new direction that the character is looking
280                 Quaternion velRotation = Quaternion.AngleAxis(transform.eulerAngles.y - oldYRotation, Vector3.up);
281                 m_RigidBody.velocity = velRotation*m_RigidBody.velocity;
282             }
283             */

284         }

285
286         ///
sphere cast down just beyond the bottom of the capsule to see if the capsule is colliding round the bottom
287         
private void GroundCheck()
288         {
289             m_PreviouslyGrounded = m_IsGrounded;
290             RaycastHit hitInfo;
291             
if (Physics.SphereCast(transform.position, m_Capsule.radius * (1.0f - advancedSettings.shellOffset), Vector3.down, out hitInfo,
292                                    ((m_Capsule.height/
2f) - m_Capsule.radius) + advancedSettings.groundCheckDistance, Physics.AllLayers, QueryTriggerInteraction.Ignore))
293             {
294                 m_IsGrounded =
true;
295                 m_GroundContactNormal = hitInfo.normal;
296             }
297             
else
298             {
299                 m_IsGrounded =
false;
300                 m_GroundContactNormal = Vector3.up;
301             }
302             
if (!m_PreviouslyGrounded && m_IsGrounded && m_Jumping)
303             {
304                 m_Jumping =
false;
305             }
306         }
307
308         
309         
private void OnCollisionEnter(Collision collision)
310         {
311             
312             
//Debug.Log("Collision with " + collision.transform.gameObject.name);
313             
//Debug.Log("x: " + start_x + " y: " + start_y + "z: " + start_z);
314
315             
if (collision.gameObject.name.StartsWith("Pine_"))
316             {
317                 Restart();
318             }
319
320         }
321     
322
323         
private void Restart()
324         {
325             transform.position =
new Vector3(start_x, start_y, start_z);
326
327             prev_x = start_x;
328             prev_y = start_y;
329             prev_z = start_z;
330         }
331     }
332 }


Gõ tìm kiếm nhanh...